import { WebSocketServer } from 'ws';
import http from 'http';
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// 石油钻井数据模拟器
class DrillingDataSimulator {
    constructor() {
        // 基础数据值（基于用户提供的示例数据）
        this.baseValues = {
            wellDepth: 4041.03,      // 井深 (m)
            torque: 6.69,            // 顶驱扭矩 (KNm)
            rpm: 71.00,              // 顶驱转速 (转/分钟)
            pressure: 29895.59,      // 立管压力 (Kpa)
            flow: 1929.58,           // 入口流量 (L/min)
            rop: 7.61,               // 钻时 (m/hr)
            wob: 12.42               // 钻压 (KDN)
        };
        
        // 每个指标的波动范围（随机增减的幅度）
        this.ranges = {
            wellDepth: { min: -0.8, max: 0.8 },    // 井深变化较小
            torque: { min: -0.3, max: 0.3 },      // 扭矩波动
            rpm: { min: -3, max: 3 },             // 转速变化
            pressure: { min: -150, max: 150 },     // 压力波动较大
            flow: { min: -30, max: 30 },           // 流量变化
            rop: { min: -0.5, max: 0.5 },          // 钻时变化
            wob: { min: -0.8, max: 0.8 }           // 钻压变化
        };
        
        // 当前值
        this.currentValues = { ...this.baseValues };
        
        // 趋势控制（模拟真实的钻井过程）
        this.trends = {
            wellDepth: 0.1,    // 井深逐渐增加
            torque: 0,         // 扭矩随机波动
            rpm: 0,            // 转速保持稳定
            pressure: 0,       // 压力随机波动
            flow: 0,           // 流量保持稳定
            rop: 0,            // 钻时随机波动
            wob: 0             // 钻压随机波动
        };
        
        this.startTime = Date.now();
    }
    
    generateData() {
        const data = {};
        const now = new Date();
        const elapsedTime = (Date.now() - this.startTime) / 1000; // 秒
        
        // 添加dt字段，格式为YYYY-MM-DD HH:mm:ss
        data.dt = now.toLocaleString('zh-CN', {
            year: 'numeric',
            month: '2-digit',
            day: '2-digit',
            hour: '2-digit',
            minute: '2-digit',
            second: '2-digit',
            hour12: false
        }).replace(/\//g, '-');
        
        Object.keys(this.baseValues).forEach(key => {
            const baseValue = this.baseValues[key];
            const range = this.ranges[key];
            const trend = this.trends[key];
            
            // 计算趋势分量（随时间的小幅变化）
            const trendComponent = trend * elapsedTime * 0.01;
            
            // 计算随机分量
            const randomComponent = (Math.random() - 0.5) * (range.max - range.min);
            
            // 计算新的当前值
            let newValue = this.currentValues[key] + trendComponent + randomComponent;
            
            // 确保井深不会减少
            if (key === 'wellDepth' && newValue < this.currentValues[key]) {
                newValue = this.currentValues[key] + Math.abs(randomComponent) * 0.1;
            }
            
            // 确保所有值为正数
            if (newValue < 0) {
                newValue = Math.abs(baseValue + randomComponent);
            }
            
            // 限制某些指标的范围
            if (key === 'rpm' && newValue > 120) newValue = 120;
            if (key === 'rpm' && newValue < 20) newValue = 20;
            if (key === 'torque' && newValue > 15) newValue = 15;
            if (key === 'torque' && newValue < 1) newValue = 1;
            
            this.currentValues[key] = newValue;
            data[key] = parseFloat(newValue.toFixed(2));
        });
        
        return data;
    }
    
    reset() {
        this.currentValues = { ...this.baseValues };
        this.startTime = Date.now();
    }
}

// WebSocket服务器
class DrillingWebSocketServer {
    constructor(port = 8080) {
        this.port = port;
        this.simulator = new DrillingDataSimulator();
        this.clients = new Set();
        this.isRunning = false;
        this.updateInterval = 1000; // 1秒更新一次
        this.updateTimer = null;
        
        this.createServer();
    }
    
    createServer() {
        // 创建HTTP服务器用于提供静态文件
        const server = http.createServer((req, res) => {
            this.handleHttpRequest(req, res);
        });
        
        // 创建WebSocket服务器
        this.wss = new WebSocketServer({ server });
        
        this.wss.on('connection', (ws, req) => {
            console.log(`新的客户端连接: ${req.socket.remoteAddress}`);
            this.clients.add(ws);
            
            // 发送初始数据
            const initialData = this.simulator.generateData();
            this.sendToClient(ws, {
                type: 'initial',
                data: initialData,
                timestamp: Date.now()
            });
            
            ws.on('message', (message) => {
                try {
                    const data = JSON.parse(message);
                    this.handleClientMessage(ws, data);
                } catch (error) {
                    console.error('解析客户端消息失败:', error);
                }
            });
            
            ws.on('close', () => {
                console.log('客户端断开连接');
                this.clients.delete(ws);
            });
            
            ws.on('error', (error) => {
                console.error('WebSocket错误:', error);
                this.clients.delete(ws);
            });
        });
        
        server.listen(this.port, () => {
            console.log(`🛢️  石油钻井监控服务器启动`);
            console.log(`📡 WebSocket服务: ws://localhost:${this.port}/ws`);
            console.log(`🌐 HTTP服务: http://localhost:${this.port}`);
            console.log(`⏰ 数据更新频率: ${this.updateInterval}ms`);
            
            this.startDataBroadcast();
        });
    }
    
    handleHttpRequest(req, res) {
        let filePath = req.url === '/' ? '/index.html' : req.url;
        filePath = path.join(__dirname, filePath);
        
        const extname = path.extname(filePath).toLowerCase();
        const mimeTypes = {
            '.html': 'text/html',
            '.js': 'text/javascript',
            '.css': 'text/css',
            '.json': 'application/json'
        };
        
        const contentType = mimeTypes[extname] || 'application/octet-stream';
        
        fs.readFile(filePath, (error, content) => {
            if (error) {
                if (error.code === 'ENOENT') {
                    res.writeHead(404, { 'Content-Type': 'text/html' });
                    res.end('<h1>404 - 文件未找到</h1>');
                } else {
                    res.writeHead(500);
                    res.end(`服务器错误: ${error.code}`);
                }
            } else {
                res.writeHead(200, { 'Content-Type': contentType });
                res.end(content, 'utf-8');
            }
        });
    }
    
    handleClientMessage(ws, data) {
        switch (data.type) {
            case 'reset':
                this.simulator.reset();
                console.log('数据模拟器已重置');
                break;
            case 'get_config':
                this.sendToClient(ws, {
                    type: 'config',
                    data: {
                        updateInterval: this.updateInterval,
                        baseValues: this.simulator.baseValues
                    }
                });
                break;
            default:
                console.log('未知消息类型:', data.type);
        }
    }
    
    startDataBroadcast() {
        if (this.isRunning) return;
        
        this.isRunning = true;
        console.log('📊 开始广播实时数据...');
        
        this.updateTimer = setInterval(() => {
            if (this.clients.size > 0) {
                const data = this.simulator.generateData();
                const message = {
                    type: 'update',
                    data: data,
                    timestamp: Date.now()
                };
                
                this.broadcast(message);
            }
        }, this.updateInterval);
    }
    
    stopDataBroadcast() {
        if (!this.isRunning) return;
        
        this.isRunning = false;
        if (this.updateTimer) {
            clearInterval(this.updateTimer);
            this.updateTimer = null;
        }
        console.log('⏹️  停止数据广播');
    }
    
    broadcast(message) {
        const messageStr = JSON.stringify(message);
        this.clients.forEach(client => {
            this.sendToClient(client, message);
        });
    }
    
    sendToClient(ws, message) {
        if (ws.readyState === 1) { // WebSocket.OPEN = 1
            ws.send(JSON.stringify(message));
        }
    }
    
    getStatus() {
        return {
            isRunning: this.isRunning,
            connectedClients: this.clients.size,
            updateInterval: this.updateInterval,
            currentValues: this.simulator.currentValues
        };
    }
}

// 命令行参数处理
const args = process.argv.slice(2);
const port = args.find(arg => arg.startsWith('--port='))?.split('=')[1] || 8080;
const interval = args.find(arg => arg.startsWith('--interval='))?.split('=')[1] || 1000;

// 创建服务器实例
const server = new DrillingWebSocketServer(port);

// 处理进程信号
process.on('SIGINT', () => {
    console.log('\n🛑 收到中断信号，正在关闭服务器...');
    server.stopDataBroadcast();
    process.exit(0);
});

process.on('SIGTERM', () => {
    console.log('\n🛑 收到终止信号，正在关闭服务器...');
    server.stopDataBroadcast();
    process.exit(0);
});

console.log(`
🛢️  石油钻井监控实时数据服务器
=====================================
使用参数:
  --port=8080      设置服务器端口 (默认: 8080)
  --interval=1000   设置数据更新间隔ms (默认: 1000)

控制命令:
  Ctrl+C           停止服务器

示例:
  node server.js --port=8080 --interval=1000
`);